package edu.xhu.view;

import edu.xhu.R;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Toast;


/**
 * 
 *    
 * 类名称：TurnplateView   
 * 类描述：   
 * 创建人： zhoujun   
 * 创建时间：2011-11-29 上午10:49:27   
 * 修改人：Administrator   
 * 修改时间：2011-11-29 上午10:49:27   
 * 修改备注：   
 * @version    
 *
 */
public class MyTurnplateView extends View implements  OnTouchListener{
	
	

	private OnTurnplateListener onTurnplateListener;
	public void setOnTurnplateListener(OnTurnplateListener onTurnplateListener) {
		this.onTurnplateListener = onTurnplateListener;
	}
	
	/**
	 * 显示随机信息
	 */
	int cnt=1;
	/**
     * handler处理消息的间隔
     */
    int delayedTime = 20;

    /**
     * 消息信号，滚动的标识
     */
    static final int play = 0;

    /**
     * 消息信号，停止滚动的标识
     */
    static final int stop = 1;

    /**
     * 上次记录的时间,计算一定时间所走过的弧度、计算速度.
     */
    double currentTime = 0;


    Paint paint=new Paint();
    
    
    
    
    
    
	
	/**
	 * 画笔：点、线
	 */
	private Paint mPaint = new Paint();
	/**
	 * 画笔：圆
	 */
	private Paint paintCircle =  new Paint();
	/**
	 * 图标列表
	 */
	private Bitmap[] icons = new Bitmap[5];
	/**
	 * point列表
	 */
	private Point[] points;
	/**
	 * 数目
	 */
	private static final int PONIT_NUM = 5;

    /**
     * 处理惯性的handler
     */
    Handler handler[]=new Handler[PONIT_NUM];

	/**
	 * 主圆的圆心坐标
	 */
	private int mPointX=0, mPointY=0;
	
	
	/**
	 * 半径
	 */
	private int mRadius = 0;
	/**
	 * 每两个点间隔的角度
	 */
	private int mDegreeDelta;
	/**
	 * 每次转动的角度差
	 */
	private int tempDegree = 0;
	/**
	 * 选中的图标标识 999：未选中任何图标
	 */
	private int chooseBtn=999;

	
	private Matrix mMatrix = new Matrix();  
	
	public MyTurnplateView(Context context, int px, int py, int radius) {
		
		super(context);		
		mPaint.setColor(Color.RED);
		mPaint.setStrokeWidth(2);
		paintCircle.setAntiAlias(true);
		paintCircle.setColor(Color.WHITE);
		
		
		
		loadIcons();
		
		
		
		mPointX = px;
		mPointY = py;
		mRadius = radius;
		
		initPoints();
		
		
		computeCoordinates();
	}
	
	/**
	 * 
	 * 方法名：loadBitmaps 
	 * 功能：装载图片
	 * 参数：
	 * @param key
	 * @param d
	 * 创建人：zhoujun  
	 * 创建时间：2011-11-28
	 */
	public void loadBitmaps(int key,Drawable d){
		Bitmap bitmap = Bitmap.createBitmap(60,60,Bitmap.Config.ARGB_8888);
		Canvas canvas = new Canvas(bitmap);
		d.setBounds(0, 0, 60, 60);
		d.draw(canvas);
		icons[key]=bitmap;
	}
	/**
	 * 
	 * 方法名：loadIcons 
	 * 功能：获取所有图片
	 * 参数：
	 * 创建人：zhoujun  
	 * 创建时间：2011-11-28
	 */
	public void loadIcons(){
		Resources r = getResources();	
		//loadBitmaps(8, r.getDrawable(R.drawable.library));
		loadBitmaps(2, r.getDrawable(R.drawable.library));
		loadBitmaps(4, r.getDrawable(R.drawable.check_u));
		//loadBitmaps(3, r.getDrawable(R.drawable.club));
		loadBitmaps(0, r.getDrawable(R.drawable.employment_i));
		//loadBitmaps(5, r.getDrawable(R.drawable.employment_i));
		loadBitmaps(1, r.getDrawable(R.drawable.feedback));
		//loadBitmaps(7, r.getDrawable(R.drawable.feedback));
		loadBitmaps(3, r.getDrawable(R.drawable.senate_s));
		//loadBitmaps(9, r.getDrawable(R.drawable.senate_s));
	}

	
	/**
	 * 
	 * 方法名：initPoints 
	 * 功能：初始化每个点
	 * 参数：
	 * 创建人：zhoujun  
	 * 创建时间：2011-11-28
	 */
	 
	private void initPoints() {
		points = new Point[PONIT_NUM];
		Point point;
		int angle = 0;
		mDegreeDelta =360/PONIT_NUM;
		
		for(int index=0; index<PONIT_NUM; index++) {
			point = new Point();
			point.angle = angle;
			angle += mDegreeDelta;
			point.bitmap = icons[index];
			point.flag=index;
			points[index] = point;
            init(points[index].bitmap,index);
			
			
		}
	}

	  /**
   * 通过此方法来控制旋转度数，如果超过360，让它求余，防止，该值过大造成越界  ls 添加
   * 
   * @param added
   */
  private void addDegree(float added) {
      deta_degree += added;
      if (deta_degree > 360 || deta_degree < -360) {
          deta_degree = deta_degree % 360;
      }
  }
	
	
	
	/**
	 * 
	 * 方法名：resetPointAngle 
	 * 功能：重新计算每个点的角度
	 * 参数：
	 * @param x
	 * @param y
	 * 创建人：zhoujun  
	 * 创建时间：2011-11-28
	 */	
	private void resetPointAngle(float x, float y) {
		//float degree = deta_degree;
		float degree = computeMigrationAngle(x,y);
		for(int index=0; index<PONIT_NUM; index++) {			
			points[index].angle += degree;		
			if(points[index].angle>360){
				points[index].angle -=360;
			}else if(points[index].angle<0){
				points[index].angle +=360;
			}
			
		}
	}
	
	/**
	 * 
	 * 方法名：computeCoordinates 
	 * 功能：计算每个点的坐标
	 * 参数：
	 * 创建人：zhoujun  
	 * 创建时间：2011-11-28
	 */
	private void computeCoordinates() {
		Point point;
		for(int index=0; index<PONIT_NUM; index++) {
			point = points[index];
			point.x = mPointX+ (float)(mRadius * Math.cos(point.angle*Math.PI/180));
			point.y = mPointY+ (float)(mRadius * Math.sin(point.angle*Math.PI/180));	
//		point.x_c = mPointX+(point.x-mPointX)/2;
//			point.y_c = mPointY+(point.y-mPointY)/2;
			//Log.e(TAG, point.angle+"");
		}
	}
	
	/**
	 * 
	 * 方法名：computeMigrationAngle 
	 * 功能：计算偏移角度
	 * 参数：
	 * @param x
	 * @param y
	 * 创建人：zhoujun  
	 * 创建时间：2011-11-28
	 *///
	private int computeMigrationAngle(float x, float y) {
		int a=0;
		float distance = (float)Math.sqrt(((x-mPointX)*(x-mPointX) + (y-mPointY)*(y-mPointY)));
		int degree = (int)(Math.acos((x-mPointX)/distance)*180/Math.PI);
		if(y < mPointY) {
			degree = -degree;
		}	
		if(tempDegree!=0){
			a = degree - tempDegree;
		}
		tempDegree=degree;
		/*if(a!=0){
			cnt=1;
		}*/
		/*if(speed!=0){
			Toast.makeText(getContext(), "cnt=1", Toast.LENGTH_SHORT).show();
			cnt=1;
		}*/
		return a;
	}
	
	
	/**
	 * 
	 * 方法名：computeCurrentDistance 
	 * 功能：计算触摸的位置与各个元点的距离
	 * 参数：
	 * @param x
	 * @param y
	 * @return
	 * 创建人：zhoujun  
	 * 创建时间：2011-11-29
	 */
	private void computeCurrentDistance(float x, float y) {

		for(Point point:points){
			float distance = (float)Math.sqrt(((x-point.x)*(x-point.x) + (y-point.y)*(y-point.y)));			
			if(distance<50){//点击了该图片
			
				chooseBtn = 999;
		
				point.isCheck = true;
				break;
			}
			else{
				
				point.isCheck = false;
				chooseBtn=  point.flag;//改变chooseBtn的值
				
				//System.out.println("chooseBtn:\n" + chooseBtn);
				//System.out.println("point.flag:\n" + point.flag);
			}
		}	
	}
	
	private void switchScreen(MotionEvent event){
		/*当用户触摸屏幕时将创建一个MotionEvent对象。MotionEvent包含关于发生触摸的位置和时间等细节信息。
		 * MotionEvent对象被传递到程序中合适的方法比如View对象的onTouchEvent()方法中。
		 * 在这些方法中我们可以分析MotionEvent对象那个，以决定要执行的操作。*/
		computeCurrentDistance(event.getX(), event.getY());
		
		
		for(Point point:points){
			if(point.isCheck)
			{
				onTurnplateListener.onPointTouch(point);
				break;
			}
		}
		//Log.e(TAG,chooseBtn+"");	
		
		
	}
	
	   
	@Override
	public boolean dispatchTouchEvent(MotionEvent event) {		
		 int action = event.getAction();
		 
		for(int index=0; index<PONIT_NUM; index++) {
	        switch (action) {
	        case MotionEvent.ACTION_DOWN:{
	        	down_x = event.getX();
                down_y = event.getY();
                current_degree = detaDegree(mPointX, mPointY, down_x, down_y);
                vRecord[index].reset();
                // handler.sendEmptyMessage(stop);
                a = a_max;

                break;

            }
	        
	        case MotionEvent.ACTION_MOVE:
	        	down_x = target_x = event.getX();
	                down_y = target_y = event.getY();
	                float degree = detaDegree(mPointX, mPointY,target_x, target_y);

	                // 滑过的弧度增量
	                float dete = degree - current_degree;
	                // 如果小于-90度说明 它跨周了，需要特殊处理350->17,
	                if (dete < -270) {
	                    dete = dete + 360;

	                    // 如果大于90度说明 它跨周了，需要特殊处理-350->-17,
	                } else if (dete > 270) {
	                    dete = dete - 360;
	                }
	                lastMoveTime = System.currentTimeMillis();
	                
	                vRecord[index].add(dete, lastMoveTime);
	                addDegree(dete);
	                current_degree = degree;
	                
	                
	                resetPointAngle(event.getX(), event.getY());//这里应用resetPointAngle
		    		computeCoordinates();//得到图片的位置
		    		
		    		
	                postInvalidate();
	                
	                break;
	        case MotionEvent.ACTION_UP:
	        {
	        	switchScreen(event);
                a = a_min;

                double lastupTime = System.currentTimeMillis();
                double detaTime = lastupTime - lastMoveTime;
                up_x = event.getX();
                up_y = event.getY();
                up_degree = detaDegree(mPointX, mPointY,up_x, up_y);
                // 放手时的速度
                speed = speed +  vRecord[index].getSpeed();
                if (speed > 0) {
                    speed = Math.min(VRecord.max_speed, speed);
                } else {
                    speed = Math.max(-VRecord.max_speed, speed);
                }
//                System.out.println("speed:" + speed);
                if (speed > 0) {
                    isClockWise = true;
                    // v = 1;
                } else {
                    isClockWise = false;
                    // v = -1;
                }
                currentTime = System.currentTimeMillis();
                
                
                		handler[index].sendEmptyMessage(0);//循环设置每一个的信号
              
                break;
            }
	        case MotionEvent.ACTION_CANCEL:
	        	//系统在运行到一定程度下无法继续响应你的后续动作时会产生此事件。
	        	//一般仅在代码中将其视为异常分支情况处理
	            break;
	        }
	}
		return true;
	}
	
	@Override
	public void onDraw(Canvas canvas) {
		
		
//		canvas.drawCircle(mPointX, mPointY, mRadius, paintCircle);
//		canvas.drawPoint(mPointX, mPointY, mPaint);
		/*Paint paint = new Paint();
		paint.setColor(Color.WHITE);
		paint.setTextSize(15.0f);
 		canvas.drawText("测试 demo", 5, 15, paint);*/
		//Bitmap bitmap = ((BitmapDrawable)(getResources().getDrawable(R.drawable.circle_bg))).getBitmap();
		
		Bitmap girlBitmap = ((BitmapDrawable)(getResources().getDrawable(R.drawable.tt8))).getBitmap();
	//canvas.drawBitmap(bitmap, 210- bitmap.getWidth()/2, 320-bitmap.getHeight()/2, null);
		
	
		canvas.drawBitmap(girlBitmap, 192- girlBitmap.getWidth()/2, 305-girlBitmap.getHeight()/2, null);
		
		
		for(int index=0; index<PONIT_NUM; index++) {
			//canvas.drawPoint(points[index].x_c, points[index].y_c, mPaint);
			drawInCenter(canvas, points[index].bitmap,points[index].angle, points[index].x,points[index].y,points[index].flag);
		}
		/*if(tempDegree!=0){
			if(speed==0){
				Toast.makeText(getContext(), "今天有个好心情！", Toast.LENGTH_SHORT).show();
			}
		}*/
	}
	
	
	 /**
     * 初始化handler与速度计算器
     */
    private void init(Bitmap bitmap,final int index) {
        vRecord[index] = new VRecord();
        
        handler[index] = new Handler() {

            @Override
            public void handleMessage(Message msg) {

                double detaTime = System.currentTimeMillis() - currentTime;
                switch (msg.what) {

                    case play: {
                        if (isClockWise) {
                            speed = speed - a * detaTime;
                            if (speed <= 0) {
                                return;
                            } else {
                            	handler[index].sendEmptyMessageDelayed(play, delayedTime);
                            }
                        } else {
                            speed = speed + a * detaTime;
                            if (speed >= 0) {
                                return;
                            } else {
                            	handler[index].sendEmptyMessageDelayed(play, delayedTime);
                            }
                        }

                        addDegree((float)(speed * detaTime + (a * detaTime * detaTime) / 2));                     
                        currentTime = System.currentTimeMillis();
                        invalidate();

                        break;
                    }
                    case stop: {
                        speed = 0;
                        handler[index].removeMessages(play);
                    }
                }

                super.handleMessage(msg);
            }
        };
}

  
    
    
	/**
	 * 
	 * 方法名：drawInCenter 
	 * 功能：把点放到图片中心处
	 * 参数：
	 * @param canvas
	 * @param bitmap
	 * @param left
	 * @param top
	 * 创建人：zhoujun  
	 * 创建时间：2011-11-28
	 */
	void drawInCenter(Canvas canvas, Bitmap bitmap,float angle, float left,float top,int flag) {
		 /*Matrix matrix = new Matrix();
		 angle=angle+deta_degree/3;
		 matrix.setTranslate(mPointX, mPointY);
		 if (angle > 360 || angle < -360) {
			 angle = angle % 360;
	      }
		 matrix.preRotate(angle);
		 matrix.preTranslate(-88, -158);
		 canvas.drawBitmap(bitmap, matrix,mPaint);*/ 
		
		 angle=angle+deta_degree;
		 if (angle > 360 || angle < -360) {
			 angle = angle % 360;
	      }
		 left = mPointX+ (float)(mRadius * Math.cos(angle*Math.PI/180));
		 top = mPointY+ (float)(mRadius * Math.sin(angle*Math.PI/180));
		 
		//left 是x，top是y
		//canvas.drawPoint(left, top, mPaint);
		
		 //System.out.println("flag:\n" + flag);
		 //System.out.println("chooseBtnjj:\n" + chooseBtn);
		 
		if(chooseBtn==flag){
			mMatrix.setScale(70f/bitmap.getWidth(), 70f/bitmap.getHeight());   
			mMatrix.postTranslate(left-35, top-35);  
			canvas.drawBitmap(bitmap, mMatrix, null);
		}
	else{
		canvas.drawBitmap(bitmap, left-bitmap.getWidth()/2, top-bitmap.getHeight()/2, null);
	}
		/*if(tempDegree!=0){
			if(speed==0){
				if(cnt==1){
					Toast.makeText(getContext(), "今天有个好心情！", Toast.LENGTH_SHORT).show();
					cnt=0;
				}
				
			}
		}*/
		/*if(speed==0){
			if(cnt==1){
				Toast.makeText(getContext(), "今天有个好心情！", Toast.LENGTH_SHORT).show();
			    cnt=0;
			}
		}
		else{
			Toast.makeText(getContext(), "cnt", Toast.LENGTH_SHORT).show();
			cnt=1;
		}*/
}
		
	
	
	
	 /**
     * 手指触屏的初始x的坐标
     */
    float down_x;

    /**
     * 手指触屏的初始y的坐标
     */
    float down_y;

    /**
     * 移动时的x的坐标
     */
    float target_x;

    /**
     * 移动时的y的坐标
     */
    float target_y;

    /**
     * 放手时的x的坐标
     */
    float up_x;

    /**
     * 放手时的y的坐标
     */
    float up_y;

    /**
     * 当前的弧度(以该 view 的中心为圆点)
     */
    float current_degree;

    /**
     * 放手时的弧度(以该 view 的中心为圆点)
     */
    float up_degree;

    /**
     * 当前圆盘所转的弧度(以该 view 的中心为圆点)
     */
    float deta_degree=0;

    /**
     * 最后一次手势滑过的时间
     */
    double lastMoveTime = 0;

    /**
     * 最小加速度（当手指放手是）
     */
    public static final float a_min = 0.001f;

    /**
     * 加速度增量
     */
    public static final float a_add = 0.001f;

    /**
     * 加速度
     */
    float a = a_min;

    /**
     * 最大加速度（当手指按住时）
     */
    public static final float a_max = a_min * 5;

    /**
     * 旋转速度(度/毫秒)
     */
    double speed = 0;

    /**
     * 速度计算器
     */
    VRecord vRecord[]=new VRecord[PONIT_NUM];

    /**
     * 是否为顺时针旋转
     */
	
    /**
     * 是否为顺时针旋转
     */
    boolean isClockWise;
	
   
    /**
     * 计算以(src_x,src_y)为坐标圆点，建立直角体系，求出(target_x,target_y)坐标与x轴的夹角
     * 主要是利用反正切函数的知识求出夹角
     * 
     * @param src_x
     * @param src_y
     * @param target_x
     * @param target_y
     * @return
     */
    float detaDegree(float src_x, float src_y, float target_x, float target_y) {

        float detaX = target_x - src_x;
        float detaY = target_y - src_y;
        double d;
        if (detaX != 0) {
            float tan = Math.abs(detaY / detaX);

            if (detaX > 0) {

                if (detaY >= 0) {
                    d = Math.atan(tan);

                } else {
                    d = 2 * Math.PI - Math.atan(tan);
                }

            } else {
                if (detaY >= 0) {

                    d = Math.PI - Math.atan(tan);
                } else {
                    d = Math.PI + Math.atan(tan);
                }
            }

        } else {
            if (detaY > 0) {
                d = Math.PI / 2;
            } else {

                d = -Math.PI / 2;
            }
        }

        return (float)((d * 180) / Math.PI);
    }

    /**
     * 一个异常，用来判断是否有rotatbitmap
     * 
     * @author sun.shine
     */
    static class NoBitMapError extends RuntimeException {

        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        public NoBitMapError(String detailMessage) {
            super(detailMessage);
        }

    }

	public class Point {
		
		/**
		 * 位置标识
		 */
		public int flag;
		/**
		 * 图片
		 */
		Bitmap bitmap;
		
		/**
		 * 角度
		 */
		float angle;
		
		/**
		 * x坐标
		 */
		float x;
		
		/**
		 * y坐标
		 */
		float y;
		
		/**
		 * 点与圆心的中心x坐标
		 */
		float x_c;
		/**
		 * 点与圆心的中心y坐标
		 */
		float y_c;
		
		boolean isCheck;
	}

	
	 /**
     * 速度计算器 原来是将最近的 弧度增量和时间点记录下来，然后<br>
     * 通过增量除以总时间求出平均值做为它的即时手势滑过的速度
     * 
     * @author sun.shine
     */
    static class VRecord {

        /**
         * 数组中的有效数字
         */
        int addCount;

        /**
         * 最大能装的数据空间
         */
        public static final int length = 15;

        /**
         * 二维数组，1.保存弧度增量.2.保存产生这个增量的时间点
         */
        double[][] record = new double[length][2];

        /**
         * 为二维数组装载数据<br>
         * 注：通过此方法，有个特点，能把最后的length组数据记录下来，length以外的会丢失
         * 
         * @param detadegree
         * @param time
         */
        public void add(double detadegree, double time) {

            for (int i = length - 1; i > 0; i--) {
                record[i][0] = record[i - 1][0];
                record[i][1] = record[i - 1][1];
            }
            record[0][0] = detadegree;
            record[0][1] = time;
            addCount++;

        }

        /**
         * 最大速度
         */
        public static final double max_speed = 6;

        /**
         * 通过数组里所装载的数据分析出即时速度<br>
         * 原理是：计算数组里的时间长度和增量的总数，然后求出每毫秒所走过的弧度<br>
         * 当然不能超过{@link VRecord#max_speed}
         * 
         * @return
         */
        public double getSpeed() {

            if (addCount == 0) {
                return 0;
            }
            int maxIndex = Math.min(addCount, length) - 1;

            if ((record[0][1] - record[maxIndex][1]) == 0) {
                return 0;
            }

            double detaTime = record[0][1] - record[maxIndex][1];
            double sumdegree = 0;
            for (int i = 0; i < length - 1; i++) {

                sumdegree += record[i][0];
                // System.out.println(record[i][0]);
            }

            // System.out.println("----------");
            // System.out.println(sumdegree);
            // System.out.println(detaTime);
            double result = sumdegree / detaTime;
            if (result > 0) {
                return Math.min(result, max_speed);
            } else {
                return Math.max(result, -max_speed);
            }
            // System.out.println("v=" + result);

        }

        /**
         * 重置
         */
        public void reset() {
            addCount = 0;
            for (int i = length - 1; i > 0; i--) {
                record[i][0] = 0;
                record[i][1] = 0;
            }
        }
    }
	
	 public static interface OnTurnplateListener {
	       
	     public void onPointTouch(Point point);
	       	             	        
	 }

	@Override
	public boolean onTouch(View arg0, MotionEvent arg1) {
		return false;
	}
	
	
}
